<template>
  <div :class="{ 'dark-mode': dark }" class="statistics-card">
    <div class="card-header">
      <div class="title-container">
        <div class="card-title">{{ title }}</div>
        <div v-if="subtitle" class="card-subtitle">{{ subtitle }}</div>
      </div>
      <div v-if="icon" class="icon-container">
        <el-icon :size="24">
          <component :is="icon"/>
        </el-icon>
      </div>
    </div>

    <div class="card-body">
      <div class="value-container">
        <div v-if="prefix" class="value-prefix">{{ prefix }}</div>
        <div class="value-number">{{ formattedValue }}</div>
        <div v-if="suffix" class="value-suffix">{{ suffix }}</div>
      </div>

      <div v-if="showComparison" class="comparison">
        <div
            :class="{
            'up': parseFloat(comparison) > 0,
            'down': parseFloat(comparison) < 0,
            'neutral': parseFloat(comparison) === 0
          }"
            class="comparison-value"
        >
          <el-icon class="comparison-icon">
            <component :is="comparisonIcon"/>
          </el-icon>
          {{ formatComparison(comparison) }}
        </div>
        <div class="comparison-label">{{ comparisonLabel }}</div>
      </div>
    </div>

    <div v-if="showChart" ref="chartContainer" class="chart-container"></div>
  </div>
</template>

<script lang="ts" setup>
import {computed, onBeforeUnmount, onMounted, ref, watch} from 'vue';
import {ArrowDown, ArrowUp, Minus} from '@element-plus/icons-vue';
import * as echarts from 'echarts/core';
import {BarChart, LineChart} from 'echarts/charts';
import {GridComponent, LegendComponent, TitleComponent, TooltipComponent} from 'echarts/components';
import {SVGRenderer} from 'echarts/renderers';

// 注册必要的组件
echarts.use([
  GridComponent,
  TooltipComponent,
  TitleComponent,
  LegendComponent,
  LineChart,
  BarChart,
  SVGRenderer
]);

// 组件属性
const props = defineProps({
  // 标题
  title: {
    type: String,
    required: true
  },
  // 子标题
  subtitle: {
    type: String,
    default: ''
  },
  // 图标
  icon: {
    type: String,
    default: ''
  },
  // 值
  value: {
    type: [Number, String],
    default: 0
  },
  // 数值前缀（例如货币符号）
  prefix: {
    type: String,
    default: ''
  },
  // 数值后缀（例如百分比）
  suffix: {
    type: String,
    default: ''
  },
  // 与上期比较的百分比
  comparison: {
    type: [Number, String],
    default: 0
  },
  // 比较标签
  comparisonLabel: {
    type: String,
    default: '与上月相比'
  },
  // 是否显示比较
  showComparison: {
    type: Boolean,
    default: true
  },
  // 是否显示图表
  showChart: {
    type: Boolean,
    default: true
  },
  // 图表类型（line/bar）
  chartType: {
    type: String,
    default: 'line'
  },
  // 图表数据
  chartData: {
    type: Array,
    default: () => []
  },
  // 图表X轴数据
  chartLabels: {
    type: Array,
    default: () => []
  },
  // 图表颜色
  chartColor: {
    type: String,
    default: '#409EFF'
  },
  // 是否是暗色模式
  dark: {
    type: Boolean,
    default: false
  },
  // 数值格式化选项
  formatOptions: {
    type: Object,
    default: () => ({
      style: 'decimal',
      maximumFractionDigits: 2,
      minimumFractionDigits: 0
    })
  }
});

// 引用图表容器
const chartContainer = ref<HTMLElement | null>(null);
let chartInstance: echarts.ECharts | null = null;

// 格式化数值
const formattedValue = computed(() => {
  if (typeof props.value === 'number') {
    try {
      return props.value.toLocaleString('zh-CN', props.formatOptions);
    } catch (e) {
      console.error('数值格式化错误:', e);
      return props.value.toString();
    }
  }
  return props.value;
});

// 比较图标
const comparisonIcon = computed(() => {
  const value = parseFloat(props.comparison as string);
  if (value > 0) return ArrowUp;
  if (value < 0) return ArrowDown;
  return Minus;
});

// 格式化比较数值为百分比
const formatComparison = (value: number | string) => {
  const numValue = parseFloat(value as string);
  const absValue = Math.abs(numValue);
  return absValue.toLocaleString('zh-CN', {
    style: 'percent',
    minimumFractionDigits: 1,
    maximumFractionDigits: 1
  });
};

// 渲染图表
const renderChart = () => {
  if (!chartContainer.value || !props.showChart) return;

  chartInstance = echarts.init(chartContainer.value);

  // 检查是否有数据
  const data = props.chartData.length > 0 ? props.chartData : [];
  const labels = props.chartLabels.length > 0 ? props.chartLabels : [];

  // 如果没有数据，显示无数据状态
  if (data.length === 0 || labels.length === 0) {
    chartInstance.setOption({
      title: {
        text: '暂无数据',
        left: 'center' as const,
        top: 'center' as const,
        textStyle: {
          color: '#909399',
          fontSize: 14,
          fontWeight: 'normal'
        }
      }
    });
    return;
  }

  // 创建图表配置
  const option = {
    grid: {
      top: 10,
      right: 10,
      bottom: 10,
      left: 10,
      containLabel: false
    },
    xAxis: {
      type: 'category',
      data: labels,
      show: false
    },
    yAxis: {
      type: 'value',
      show: false
    },
    series: [
      {
        data: data,
        type: props.chartType,
        smooth: true,
        showSymbol: false,
        lineStyle: {
          width: 2,
          color: props.chartColor
        },
        itemStyle: {
          color: props.chartColor
        },
        areaStyle: props.chartType === 'line' ? {
          color: {
            type: 'linear',
            x: 0,
            y: 0,
            x2: 0,
            y2: 1,
            colorStops: [
              {offset: 0, color: props.chartColor + '80'},
              {offset: 1, color: props.chartColor + '10'}
            ]
          }
        } : undefined
      }
    ],
    tooltip: {
      trigger: 'axis',
      formatter: '{b}: {c}'
    },
    animation: true
  };

  // 设置图表
  chartInstance.setOption(option);
};

// 监听窗口大小变化
const handleResize = () => {
  if (chartInstance) {
    chartInstance.resize();
  }
};

// 监听属性变化
watch(() => [props.chartData, props.chartLabels, props.chartType, props.chartColor], () => {
  if (chartInstance) {
    chartInstance.dispose();
    renderChart();
  }
});

// 组件挂载时初始化
onMounted(() => {
  renderChart();
  window.addEventListener('resize', handleResize);
});

// 组件卸载前清理
onBeforeUnmount(() => {
  if (chartInstance) {
    chartInstance.dispose();
    chartInstance = null;
  }
  window.removeEventListener('resize', handleResize);
});
</script>

<style scoped>
.statistics-card {
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  padding: 16px;
  height: 100%;
  display: flex;
  flex-direction: column;
  transition: box-shadow 0.3s;
}

.statistics-card:hover {
  box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.15);
}

.statistics-card.dark-mode {
  background-color: #1c2128;
  color: #e3e3e3;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 16px;
}

.title-container {
  display: flex;
  flex-direction: column;
}

.card-title {
  font-size: 16px;
  color: #606266;
  font-weight: 500;
}

.dark-mode .card-title {
  color: #c9c9c9;
}

.card-subtitle {
  font-size: 12px;
  color: #909399;
  margin-top: 4px;
}

.icon-container {
  color: #909399;
  display: flex;
  align-items: center;
  justify-content: center;
}

.card-body {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 16px;
}

.value-container {
  display: flex;
  align-items: baseline;
}

.value-prefix {
  font-size: 16px;
  margin-right: 4px;
  color: #606266;
}

.value-number {
  font-size: 24px;
  font-weight: 600;
  color: #303133;
}

.dark-mode .value-number {
  color: #ffffff;
}

.value-suffix {
  font-size: 14px;
  margin-left: 4px;
  color: #606266;
}

.comparison {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
}

.comparison-value {
  display: flex;
  align-items: center;
  font-size: 14px;
  font-weight: 500;
}

.comparison-value.up {
  color: #f56c6c;
}

.comparison-value.down {
  color: #67c23a;
}

.comparison-value.neutral {
  color: #909399;
}

.comparison-icon {
  margin-right: 4px;
}

.comparison-label {
  font-size: 12px;
  color: #909399;
  margin-top: 2px;
}

.chart-container {
  flex-grow: 1;
  min-height: 80px;
}
</style> 